package com.ndood.polling.domain.receive.v1.service;

import java.util.Date;

import org.apache.http.util.Asserts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alipay.api.response.AlipayTradeCancelResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.google.gson.Gson;
import com.ndood.PollingApplication;
import com.ndood.api.app.properties.ApiProperties;
import com.ndood.api.app.sdk.alipay.f2f.model.builder.AlipayTradeCancelRequestBuilder;
import com.ndood.api.app.sdk.alipay.f2f.model.builder.AlipayTradeQueryRequestBuilder;
import com.ndood.api.app.sdk.alipay.f2f.model.result.AlipayF2FCancelResult;
import com.ndood.api.app.sdk.alipay.f2f.model.result.AlipayF2FQueryResult;
import com.ndood.api.app.sdk.alipay.f2f.service.AlipayTradeService;
import com.ndood.api.app.sdk.alipay.f2f.utils.AlipayBuilderUtils;
import com.ndood.api.base.constaints.ApiCode;
import com.ndood.api.base.exception.ApiException;
import com.ndood.api.domain.record.receive.v1.entity.dto.RecoRecPayDto;
import com.ndood.api.domain.record.receive.v1.service.RecoRecPlatformOfflineOfficialAlif2fService;
import com.ndood.api.domain.support.merchant.entity.dto.SupportMchRecConfigDto;
import com.ndood.api.domain.support.merchant.service.SupportMchRecConfigService;
import com.ndood.common.base.constaints.CommonConstaints;
import com.ndood.polling.app.task.PollingDelayTask;
import com.ndood.polling.app.task.PollingParam;
import com.ndood.polling.base.constaints.PollingConstaints;
import com.ndood.polling.domain.polling.v1.service.PollingService;

import lombok.extern.slf4j.Slf4j;

/**
 * 收款能力-平台收款-官方支付宝当面付 服务类
 */
@Service
@Slf4j
public class RecPlatformOfflineOfficialAlif2fService {

	@Autowired
	private PollingService pollingService;

	@Autowired
	private ApiProperties apiProperties;

	@Autowired
	private SupportMchRecConfigService supportMchRecConfigService;

	@Autowired
	private RecoRecPlatformOfflineOfficialAlif2fService recoRecPlatformOfflineOfficialAlif2fService;

	/**
	 * 1 查询条码支付结果
	 */
	public void queryBar(RecoRecPayDto payOrder, PollingParam param) throws ApiException {

		// Step1 处理直清支付
		if (CommonConstaints.CONTRACT_TYPE_DIRECT.equals(payOrder.getContractType())) {

			// 1 获取直清商户支付配置
			SupportMchRecConfigDto config = supportMchRecConfigService.getMerchantReceiveConfig(payOrder.getMchId());
			Asserts.notNull(config, "商户直清收款配置不存在!");
			AlipayTradeService tradeService = AlipayBuilderUtils
					.buildAlipayTradeService(apiProperties.getPay().getAlipayGateway(),
							config.getAliAlipayPublicRsa2Secret(), config.getAliAppId(),
							config.getAliMchPrivateRsa2Secret());

			// 2 组装支付请求
			AlipayTradeQueryRequestBuilder builder = new AlipayTradeQueryRequestBuilder()
					.setOutTradeNo(payOrder.getPayOrderNo());
			AlipayF2FQueryResult result = tradeService.queryTradeResult(builder);
			log.info(new Gson().toJson(result));

			AlipayTradeQueryResponse response = result.getResponse();

			// 3: 处理订单
			switch (result.getTradeStatus()) {
			case SUCCESS:

				String tradeStatus = response.getTradeStatus();
				// 交易状态：WAIT_BUYER_PAY（交易创建，等待买家付款）、TRADE_CLOSED（未付款交易超时关闭，或支付完成后全额退款）、TRADE_SUCCESS（交易支付成功）、TRADE_FINISHED（交易结束，不可退款）
				// 实施查询只需要考虑 支付中和支付成功
				if ("TRADE_SUCCESS".equals(tradeStatus)) {
					recoRecPlatformOfflineOfficialAlif2fService.pollingSuccess(payOrder, response);
					return;
				}

				// 支付中 如果轮询次数小于最大次数，则继续轮询
				if (param.getCount() < apiProperties.getPolling().getMax_query_retry()) {
					param.setCount(param.getCount() + 1);
					// 否则进行撤销
				} else {
					param.setFlag(PollingConstaints.POLLING_CANCEL);
					param.setCount(1);
					param.setDuration(apiProperties.getPolling().getCancel_duration());
					param.setMaxCount(apiProperties.getPolling().getMax_cancel_retry());
					param.setCreateTime(new Date());
				}
				// 将任务放入延时队列
				PollingApplication.tasks.put(new PollingDelayTask(param, pollingService));
				return;

			case FAILED:
			case UNKNOWN:
			default:

				// 轮询失败 如果轮询次数小于最大次数，则继续轮询
				if (param.getCount() < apiProperties.getPolling().getMax_query_retry()) {
					param.setCount(param.getCount() + 1);
					// 否则进行撤销
				} else {
					param.setFlag(PollingConstaints.POLLING_CANCEL);
					param.setCount(1);
					param.setDuration(apiProperties.getPolling().getCancel_duration());
					param.setMaxCount(apiProperties.getPolling().getMax_cancel_retry());
					param.setCreateTime(new Date());
				}
				// 将任务放入延时队列
				PollingApplication.tasks.put(new PollingDelayTask(param, pollingService));
				return;

			}

		}

		// Step2: 处理二清支付
		if (CommonConstaints.CONTRACT_TYPE_SECOND.equals(payOrder.getContractType())) {

			// 1 获取直清商户支付配置
			AlipayTradeService tradeService = AlipayBuilderUtils
					.buildAlipayTradeService(apiProperties.getPay().getAlipayGateway(),
							apiProperties.getPay().getAlipayRsa2PublicSecret(),
							apiProperties.getPay().getAlipayAppId(),
							apiProperties.getPay().getAlipayMchRsa2PrivateSecret());

			// 2 组装支付请求
			AlipayTradeQueryRequestBuilder builder = new AlipayTradeQueryRequestBuilder()
					.setOutTradeNo(payOrder.getPayOrderNo());
			AlipayF2FQueryResult result = tradeService.queryTradeResult(builder);

			log.info(new Gson().toJson(result));

			AlipayTradeQueryResponse response = result.getResponse();
			// 3: 处理订单
			switch (result.getTradeStatus()) {
			case SUCCESS:
				
				String tradeStatus = response.getTradeStatus();
				// 交易状态：WAIT_BUYER_PAY（交易创建，等待买家付款）、TRADE_CLOSED（未付款交易超时关闭，或支付完成后全额退款）、TRADE_SUCCESS（交易支付成功）、TRADE_FINISHED（交易结束，不可退款）
				// 实施查询只需要考虑 支付中和支付成功
				if ("TRADE_SUCCESS".equals(tradeStatus)) {
					recoRecPlatformOfflineOfficialAlif2fService.pollingSuccess(payOrder, response);
					return;
				}

				// 支付中 如果轮询次数小于最大次数，则继续轮询
				if (param.getCount() < apiProperties.getPolling().getMax_query_retry()) {
					param.setCount(param.getCount() + 1);
					// 否则进行撤销
				} else {
					param.setFlag(PollingConstaints.POLLING_CANCEL);
					param.setCount(1);
					param.setDuration(apiProperties.getPolling().getCancel_duration());
					param.setMaxCount(apiProperties.getPolling().getMax_cancel_retry());
					param.setCreateTime(new Date());
				}
				// 将任务放入延时队列
				PollingApplication.tasks.put(new PollingDelayTask(param, pollingService));
				return;
				
			case FAILED:
			case UNKNOWN:
			default:
				
				// 轮询失败 如果轮询次数小于最大次数，则继续轮询
				if (param.getCount() < apiProperties.getPolling().getMax_query_retry()) {
					param.setCount(param.getCount() + 1);
					// 否则进行撤销
				} else {
					param.setFlag(PollingConstaints.POLLING_CANCEL);
					param.setCount(1);
					param.setDuration(apiProperties.getPolling().getCancel_duration());
					param.setMaxCount(apiProperties.getPolling().getMax_cancel_retry());
					param.setCreateTime(new Date());
				}
				// 将任务放入延时队列
				PollingApplication.tasks.put(new PollingDelayTask(param, pollingService));
				return;
				
			}

		}

		throw new ApiException(ApiCode.ERR_SERVER, "不支持的清算合同类型！");

	}

	/**
	 * 2 撤销条码支付结果
	 */
	public void cancelBar(RecoRecPayDto payOrder, PollingParam param) throws ApiException {
		
		// Step1 处理直清支付
		if (CommonConstaints.CONTRACT_TYPE_DIRECT.equals(payOrder.getContractType())) {

			// 1 获取直清商户支付配置
			SupportMchRecConfigDto config = supportMchRecConfigService.getMerchantReceiveConfig(payOrder.getMchId());
			Asserts.notNull(config, "商户直清收款配置不存在!");
			AlipayTradeService tradeService = AlipayBuilderUtils
					.buildAlipayTradeService(apiProperties.getPay().getAlipayGateway(),
							config.getAliAlipayPublicRsa2Secret(), config.getAliAppId(),
							config.getAliMchPrivateRsa2Secret());

			// 2 组装支付请求
			AlipayTradeCancelRequestBuilder builder = new AlipayTradeCancelRequestBuilder()
					.setOutTradeNo(payOrder.getPayOrderNo());
			AlipayF2FCancelResult result = tradeService.cancelTrade(builder);
			log.info(new Gson().toJson(result));

			AlipayTradeCancelResponse response = result.getResponse();
			
			// 3: 处理订单
			switch (result.getTradeStatus()) {
			case SUCCESS:
				
				// 记账支付已取消
				recoRecPlatformOfflineOfficialAlif2fService.pollingCancel(payOrder, response);
				return;
				
			case FAILED:
			default:
				
				// 轮询失败 如果轮询次数小于最大次数，则继续轮询
				if (param.getCount() < apiProperties.getPolling().getMax_cancel_retry()) {
					param.setCount(param.getCount() + 1);
					// 将任务放入延时队列
					PollingApplication.tasks.put(new PollingDelayTask(param, pollingService));
				} else {
					// 对于撤销多次都失败的订单，查询一次，成功的化查询转支付，失败的化记录异常日志人工处理
					doWithCancelFailed(payOrder);
				}
				return;
				
			}
		}
		
		// Step2: 处理二清支付
		if (CommonConstaints.CONTRACT_TYPE_SECOND.equals(payOrder.getContractType())) {
			// 1 获取直清商户支付配置
			AlipayTradeService tradeService = AlipayBuilderUtils
					.buildAlipayTradeService(apiProperties.getPay().getAlipayGateway(),
							apiProperties.getPay().getAlipayRsa2PublicSecret(),
							apiProperties.getPay().getAlipayAppId(),
							apiProperties.getPay().getAlipayMchRsa2PrivateSecret());

			// 2 组装支付请求
			AlipayTradeCancelRequestBuilder builder = new AlipayTradeCancelRequestBuilder()
					.setOutTradeNo(payOrder.getPayOrderNo());
			AlipayF2FCancelResult result = tradeService.cancelTrade(builder);
			log.info(new Gson().toJson(result));

			AlipayTradeCancelResponse response = result.getResponse();
			
			// 3: 处理订单
			switch (result.getTradeStatus()) {
			case SUCCESS:
				
				// 记账支付已取消
				recoRecPlatformOfflineOfficialAlif2fService.pollingCancel(payOrder, response);
				return;
				
			case FAILED:
			default:
				
				// 轮询失败 如果轮询次数小于最大次数，则继续轮询
				if (param.getCount() < apiProperties.getPolling().getMax_cancel_retry()) {
					param.setCount(param.getCount() + 1);
					// 将任务放入延时队列
					PollingApplication.tasks.put(new PollingDelayTask(param, pollingService));
				} else {
					// 对于撤销多次都失败的订单，查询一次，成功的化查询转支付，失败的化记录异常日志人工处理
					doWithCancelFailed(payOrder);
				}
				return;
				
			}
		}
		
		throw new ApiException(ApiCode.ERR_SERVER, "不支持的清算合同类型！");
		
	}

	/**
	 * 3 撤销失败处理 再查询一次，如果成功记录成功订单。如果失败，记录订单异常
	 */
	private void doWithCancelFailed(RecoRecPayDto payOrder) throws ApiException {
		
		// Step1 处理直清支付
		if (CommonConstaints.CONTRACT_TYPE_DIRECT.equals(payOrder.getContractType())) {

			// 1 获取直清商户支付配置
			SupportMchRecConfigDto config = supportMchRecConfigService.getMerchantReceiveConfig(payOrder.getMchId());
			Asserts.notNull(config, "商户直清收款配置不存在!");
			AlipayTradeService tradeService = AlipayBuilderUtils
					.buildAlipayTradeService(apiProperties.getPay().getAlipayGateway(),
							config.getAliAlipayPublicRsa2Secret(), config.getAliAppId(),
							config.getAliMchPrivateRsa2Secret());

			// 2 组装支付请求
			AlipayTradeQueryRequestBuilder builder = new AlipayTradeQueryRequestBuilder()
					.setOutTradeNo(payOrder.getPayOrderNo());
			AlipayF2FQueryResult result = tradeService.queryTradeResult(builder);
			log.info(new Gson().toJson(result));

			AlipayTradeQueryResponse response = result.getResponse();

			// 3: 处理订单
			switch (result.getTradeStatus()) {
			case SUCCESS:

				String tradeStatus = response.getTradeStatus();
				// 交易状态：WAIT_BUYER_PAY（交易创建，等待买家付款）、TRADE_CLOSED（未付款交易超时关闭，或支付完成后全额退款）、TRADE_SUCCESS（交易支付成功）、TRADE_FINISHED（交易结束，不可退款）
				// 实施查询只需要考虑 支付中和支付成功
				if ("TRADE_SUCCESS".equals(tradeStatus)) {
					recoRecPlatformOfflineOfficialAlif2fService.pollingSuccess(payOrder, response);
					return;
				}
				
				// 标记为异常订单
				recoRecPlatformOfflineOfficialAlif2fService.pollingCancelFailed(payOrder, response);
				return;
				
			case FAILED:
			case UNKNOWN:
			default:
				
				// 标记为异常订单
				recoRecPlatformOfflineOfficialAlif2fService.pollingCancelFailed(payOrder, response);
				return;
				
			}

		}

		// Step2: 处理二清支付
		if (CommonConstaints.CONTRACT_TYPE_SECOND.equals(payOrder.getContractType())) {

			// 1 获取直清商户支付配置
			AlipayTradeService tradeService = AlipayBuilderUtils
					.buildAlipayTradeService(apiProperties.getPay().getAlipayGateway(),
							apiProperties.getPay().getAlipayRsa2PublicSecret(),
							apiProperties.getPay().getAlipayAppId(),
							apiProperties.getPay().getAlipayMchRsa2PrivateSecret());

			// 2 组装支付请求
			AlipayTradeQueryRequestBuilder builder = new AlipayTradeQueryRequestBuilder()
					.setOutTradeNo(payOrder.getPayOrderNo());
			AlipayF2FQueryResult result = tradeService.queryTradeResult(builder);

			log.info(new Gson().toJson(result));

			AlipayTradeQueryResponse response = result.getResponse();
			// 3: 处理订单
			switch (result.getTradeStatus()) {
			case SUCCESS:
				
				String tradeStatus = response.getTradeStatus();
				// 交易状态：WAIT_BUYER_PAY（交易创建，等待买家付款）、TRADE_CLOSED（未付款交易超时关闭，或支付完成后全额退款）、TRADE_SUCCESS（交易支付成功）、TRADE_FINISHED（交易结束，不可退款）
				// 实施查询只需要考虑 支付中和支付成功
				if ("TRADE_SUCCESS".equals(tradeStatus)) {
					recoRecPlatformOfflineOfficialAlif2fService.pollingSuccess(payOrder, response);
					return;
				}
				
				// 标记为异常订单
				recoRecPlatformOfflineOfficialAlif2fService.pollingCancelFailed(payOrder, response);
				return;

			case FAILED:
			case UNKNOWN:
			default:
				
				// 标记为异常订单
				recoRecPlatformOfflineOfficialAlif2fService.pollingCancelFailed(payOrder, response);
				return;
				
			}

		}

		throw new ApiException(ApiCode.ERR_SERVER, "不支持的清算合同类型！");
		
	}

}
